﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;

namespace DCT.CodeBox.Utility
{
    /// <summary>
    /// Xml工具类
    /// </summary>
    public static class XmlUtility
    {
        /// <summary>
        /// Xml默认声明
        /// </summary>
        public static string DEFAULT_XML_DECLARATION = "<?xml version=\"1.0\" encoding=\"utf-8\" ?>";

        /// <summary>
        /// 加载Xml
        /// </summary>
        /// <param name="xml">xml内容，不允许为空或空字符串</param>
        /// <returns></returns>
        public static XmlDocument Load(string xml)
        {
            if (string.IsNullOrEmpty(xml))
            {
                throw ExceptionUtility.StringEmptyOrNullException("XmlUtility.Load(string xml)", "xml");
            }

            XmlDocument doc = new XmlDocument();
            xml = xml.Trim();

            if (!xml.StartsWith("<?xml version="))
            {
                //自动追加xml
                xml = DEFAULT_XML_DECLARATION + xml;
            }

            doc.LoadXml(xml);

            return doc;
        }

        /// <summary>
        /// 根据一个根节点，创建一个XmlDocument
        /// </summary>
        /// <param name="rootElementTagName"></param>
        /// <returns></returns>
        public static XmlDocument CreateEmptyXmlDocument(string rootElementTagName)
        {
            if (string.IsNullOrEmpty(rootElementTagName))
            {
                throw ExceptionUtility.StringEmptyOrNullException("XmlUtility.CreateEmptyXmlDocument(string rootElementTagName)"
                    , "rootElementTagName");
            }

            rootElementTagName = rootElementTagName.Trim();

            string xml = DEFAULT_XML_DECLARATION + "<" + rootElementTagName + "/>";
            XmlDocument doc = new XmlDocument();
            doc.LoadXml(xml);
            return doc;
        }

        /// <summary>
        /// 获取Node的值，兼容CDATA；如果node参数为空，则返回空字符串
        /// </summary>
        /// <param name="node">节点元素</param>
        /// <returns></returns>
        public static string GetNodeInnerText(XmlNode node)
        {
            return GetNodeInnerText(node, "");
        }

        /// <summary>
        /// 获取Node的值，兼容CDATA
        /// </summary>
        /// <param name="node">节点元素</param>
        /// <param name="defaultVal">如果node为空时，默认值</param>
        /// <returns></returns>
        public static string GetNodeInnerText(XmlNode node, string defaultVal)
        {
            string val = defaultVal;
            if (node != null)
            {
                //查看是否有下一层，CDATA
                if (node.ChildNodes.Count > 0)
                {
                    node = node.ChildNodes[0];
                }

                val = node.InnerText ?? defaultVal;
            }
            return val;
        }

        /// <summary>
        ///  获取Node的Attribute值；如果node参数为空，则返回空字符串
        /// </summary>
        /// <param name="node">节点元素</param>
        /// <param name="attr">Attribute名称</param>
        /// <returns></returns>
        public static string GetNodeAttr(XmlNode node, string attr)
        {
            return GetNodeAttr(node, attr, "");
        }

        /// <summary>
        /// 获取Node的Attribute值
        /// </summary>
        /// <param name="node">节点元素</param>
        /// <param name="attr">Attribute名称</param>
        /// <param name="defaultVal">如果Attribute为空时的默认值</param>
        /// <returns></returns>
        public static string GetNodeAttr(XmlNode node, string attr, string defaultVal)
        {
            string val = defaultVal;
            if (node != null && node.Attributes[attr] != null && !string.IsNullOrEmpty(node.Attributes[attr].Value))
            {
                val = node.Attributes[attr].Value;
            }
            return val;
        }

        public static string FormatXml(string xmlString)
        {
            return FormatXml(xmlString, Encoding.UTF8);
        }

        public static string FormatXml(string xmlString, Encoding encoding)
        {
            return FormatXml(xmlString, encoding, Environment.NewLine, "\t");
        }

        public static string FormatXml(string xmlString, Encoding encoding, string newline, string tab)
        {
            XmlDocument document = new XmlDocument();
            document.LoadXml(xmlString);

            StringBuilder formatString = new StringBuilder();

            XmlWriterSettings setting = new XmlWriterSettings();
            setting.CheckCharacters = false;
            setting.Encoding = encoding;
            setting.Indent = true;
            setting.IndentChars = tab.ToString();
            setting.NewLineChars = newline;
            using (XmlWriter writer = XmlWriter.Create(formatString, setting))
            {
                document.WriteTo(writer);
            }
            return formatString.ToString();
        }
    }
}
